iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 18
0
Modern Web

Angular 全集中筆記系列 第 18

第 18 型 - 服務 (Service)

  • 分享至 

  • xImage
  •  

在 Angular 應用程式中,元件 (Component)、指令 (Direcitve) 與管道 (Pipe) 皆負責針對操作頁面的顯示與邏輯;而在資料方面的處理,如從伺服器取得資料等,則會是服務 (Service) 的職責,然後透過依賴注入 (Dependency Injection, DI) 的方式在元件中建立實體。這一篇先建立一 TaskService 服務,將原在 AppComponent 中待辦事項清單初始作業移至此服務中,由此服務負責待辦事項清單的處理。

利用 Angular CLI 建立待辦事項服務

首先,在終端機執行 ng g s task/services/task-local 建立待辦事項服務。

ng generate service [名稱 或 路徑] [參數]
-- 或 --
ng g s [名稱 或 路徑] [參數]

Service

接下來,在 task-local.service.ts 中,加入待辦事項清單屬性,以及對其初始化,並加入 getTasks() 方法供外部取得待辦事項清單資料。

import { Injectable } from "@angular/core";

import { TaskState } from "../../enum/task-state.enum";
import { Task } from "../../model/task";

@Injectable({
  providedIn: "root",
})
export class TaskLocalService {
  private _tasks: Task[];

  constructor() {
    this._tasks = [
      new Task("頁面需要顯示待辦事項主旨"),
      new Task("可以設定待辦事項的狀態", TaskState.Doing),
      new Task("當待辦事項狀態為已完的事項無法編輯事項", TaskState.Finish),
    ];
    this._tasks[0].level = "XS";
    this._tasks[0].tags = ["FEATURE", "ISSUE", "enhancement", "discussion"];

    this._tasks[1].level = "S";
    this._tasks[1].tags = ["Feature", "Issue", "document"];
    this._tasks[1].expectDate = new Date(2020, 10, 1);

    this._tasks[2].level = "M";
    this._tasks[2].tags = ["feature", "issue"];
    this._tasks[2].expectDate = new Date(2020, 9, 1);
    this._tasks[2].finishedDate = new Date(2020, 9, 1);
  }

  getData(): Task[] {
    return this._tasks;
  }
}

透過依賴注入 (Dependency Injection, DI) 使用待辦事項服務

實務上要在 TaskList 元件中使用待辦事項服務,最直接的作法是可以在 task-list.component.ts 中利用 new 關鍵字建立服務實體,並將待辦事項清單資料從外部傳入修改由此服務的 getData() 取得。

import { Component, Input, OnInit } from "@angular/core";

import { Task } from "../../model/task";
import { TaskLocalService } from "../services/task-local.service";

@Component({
  selector: "app-task-list",
  templateUrl: "./task-list.component.html",
  styleUrls: ["./task-list.component.css"],
})
export class TaskListComponent implements OnInit {
  tasks: Task[];

  taskService: TaskLocalService;

  constructor() {}

  ngOnInit(): void {
    this.taskService = new TaskLocalService();
    this.tasks = this.taskService.getData();
  }
}

原在 app.component.html 檔案中的按鈕區塊,因未來實作上不需使用,故在此刪除。

結果

雖然利用上述程式可以完成實作需求,不過也使得 TaskListComponent 與 TaskServce 互相依賴 (dependency) 而有高度的耦合;未來若有相關需求的變更時,就會需要修改到此兩支程式。

依賴注入 (Dependency Injection, DI) 是一種設計模式,為了要降低元件與服務之間的依賴,可以利用此設計模式,將服務實體由元件內建立修改成從外部建立後傳入。而在 Angular 內建了 DI 框架,此框架會在元件實體化時,提供此元件所宣告的依賴實體。因此可以修改 task-list.component.ts 檔案,利用建構式將待辦事項服務實體注入至此元件內。

import { Component, Input, OnInit } from "@angular/core";

import { Task } from "../../model/task";
import { TaskLocalService } from "../services/task-local.service";

@Component({
  selector: "app-task-list",
  templateUrl: "./task-list.component.html",
  styleUrls: ["./task-list.component.css"],
})
export class TaskListComponent implements OnInit {
  tasks: Task[];

  constructor(private taskService: TaskLocalService) {}

  ngOnInit(): void {
    this.tasks = this.taskService.getData();
  }
}

結論

這一篇透過服務 (Service) 將待辦事項清單資料抽離元件內,實作程式碼放在 GitHub。不過在實務上常會透過後端服務從伺服務中取得資料,因而下一篇將使用 Angular 內建的服務從伺服器中取得資料。


上一篇
第 17 型 - Angular 生命週期 (Lifecycle) - AfterViewInit / AfterViewChecked
下一篇
第 19 型 - HttpClient
系列文
Angular 全集中筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言